package com.arlen.general.controller;


import com.arlen.general.exceptionHandle.WxCustomException;
import com.arlen.general.pojo.BaseMessage;
import com.arlen.general.pojo.dto.CutInWxDto;
import com.arlen.general.util.ErrorMesUtils;
import com.arlen.general.util.MessageThread;
import com.arlen.general.util.WxMessageUtil;
import com.thoughtworks.xstream.XStream;
import org.apache.commons.beanutils.BeanUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotNull;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Map;
import java.util.Optional;

@Controller
@RequestMapping("cutIn")
public class CutInController {
    private static final Logger logger = LoggerFactory.getLogger(CutInController.class);

    @Value("${wx.token}")
    private String token;

    //进行微信的认证
    @GetMapping
    public String getCutIn(HttpServletRequest request, HttpServletResponse response) {
        Map<String, String[]> parameterMap = request.getParameterMap();
        Optional<Map<String, String[]>> optional = Optional.ofNullable(parameterMap);
        if (!optional.isPresent() || parameterMap.size() < 4) {
            throw new RuntimeException("Certification Parameter error!");
        }
        CutInWxDto cutInWxDto = new CutInWxDto();
        try {
            BeanUtils.populate(cutInWxDto, parameterMap);
        } catch (IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
        }
        if (verify(cutInWxDto, token)) {
            //3)如果比较成功直接原样返回echostr
            try (PrintWriter writer = response.getWriter()) {
                writer.write(cutInWxDto.getEchostr());
            } catch (IOException e) {
                logger.warn(e.getMessage(), e);
            }
            return "win";
        }
        return "fail";
    }

    private boolean verify(CutInWxDto cDto, @NotNull String token) {
        boolean flag = false;
        //1）将token、timestamp、nonce三个参数进行字典序排序
        String[] str = {token, cDto.getTimestamp(), cDto.getNonce()};
        Arrays.sort(str);
        //2）将三个参数字符串拼接成一个字符串进行sha1加密
        String tmpStr = str[0] + str[1] + str[2];
        String sha1Str = sha1(tmpStr);
        if (sha1Str.equalsIgnoreCase(cDto.getSignature())) {
            flag = true;
        }
        return flag;
    }

    //进行sha1加密
    private String sha1(String tmpStr) {
        MessageDigest messageDigest = null;
        try {
            //获取一个sha1加密对象
            messageDigest = MessageDigest.getInstance("sha1");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        assert messageDigest != null;
        byte[] bytes = messageDigest.digest(tmpStr.getBytes());
        char[] chars = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
        StringBuilder builder = new StringBuilder();
        for (byte aByte : bytes) {
            //每一个bate都是8个0或1 bate没四个数字就可以变成一个16进制
            //(aByte>>4)&15   aByte>>4 进行位运取前四位
            // &15 进行位运算之后就相当与将前四个0或1往后移替换掉后四个那前面的数也许会变成-1
            //byte&15后有限选择前面的数尽享16近
            builder.append(chars[(aByte >> 4) & 15]);
            builder.append(chars[(aByte) & 15]);
        }
        return builder.toString();
    }

    @Autowired
    ErrorMesUtils errorMesUtils;

    //接收用户通过公众号发送的消息
    @PostMapping
    public void getMessage(HttpServletResponse response, HttpServletRequest request) {
        try {
            request.setCharacterEncoding("utf-8");
            response.setContentType("application/json;charset=utf-8");
        } catch (UnsupportedEncodingException e) {
           logger.warn("set charset exception!");
        }

        //使用工具类解析微信用户传输信息
        Map<String, String> messageMap = MessageThread.getMessageThread();

        try(PrintWriter writer = response.getWriter()) {
            BaseMessage baseMessage = WxMessageUtil.responseMessage(messageMap);
            if (null == baseMessage){
                errorMesUtils.captureExcept(response,request,"功能暂未开放");
                return;
            }
            //创建XStream对象
            XStream xStream = new XStream();
            String className = baseMessage.getClass().getName();
            xStream.processAnnotations(Class.forName(className));//就算我们加上@XStreamAlias 注解还是不好使 我们还需要加上这个配置
            String mesXml = xStream.toXML(baseMessage);
            writer.write(mesXml);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }


}
